﻿using NetSDKCS;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Configuration;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using CaseManagerLibrary.Models;
using CaseManagerLibrary.Http;
using CaseManagerLibrary.Auth;
using CaseManagerLibrary.Socket;
using System.Net;
using PSDLib.Models;
using PSDLib.Protocols;
using PSDClient.Protocols;
using PSDLib.Ctrl;
using System.Management;
using System.IO;
using PSDLib;

namespace PSDClient.Service
{
    public delegate void ReloadTaskEventHandler();
    public delegate void CreateTaskEventHandler(dl_task task, List<dl_task_channel> channels);
    public delegate void CreateChannelEventHandler(dl_task_channel channel);
    public delegate void RemoveChannelEventHandler(dl_task_channel channel);
    public delegate void CreateDownloadEventHandler(dl_files file);
    public delegate void FileDownloadSuccessEventHandler(dl_files file);
    public delegate void FileDownloadFailedEventHandler(dl_files file);
    public delegate void UpdateDownloadProgressEventHandler(dl_files file, int time);
    public delegate void StartDownloadEventHandler();
    public delegate void StopDownloadEventHandler();
    public delegate void ClosingEventHandler();
    public delegate void DownloadStateChangedEventHandler(string id, int state);
    public delegate void SetDeviceInfoEventHandler(dl_download_device device);

    public class DownloadHelper
    {
        //public event ReloadTaskEventHandler OnReload;
        public event CreateTaskEventHandler OnCreateTask;
        public event CreateChannelEventHandler OnCreateChannel;
        public event RemoveChannelEventHandler OnRemoveChannel;
        public event CreateDownloadEventHandler OnCreateDownload;
        public event FileDownloadSuccessEventHandler OnFileDownloadSuccess;
        public event FileDownloadFailedEventHandler OnFileDownloadFail;
        public event UpdateDownloadProgressEventHandler OnUpdateDownloadProgress;
        public event StartDownloadEventHandler OnStartDownload;
        public event StopDownloadEventHandler OnStopDownload;
        public event ClosingEventHandler OnClosing;
        public event DownloadStateChangedEventHandler OnDownloadTaskStateChanged;
        public event DownloadStateChangedEventHandler OnDownloadChannelStateChanged;
        public event SetDeviceInfoEventHandler OnSetDeviceInfo;

        //private  object running_lock = new object();
        //private  object downloader_lock = new object();
        //private  object waitlist_lock = new object();
        public PSDClientDevice PSDClient { get; set; }
        public bool Running { get; private set; }
        public bool Downloading { get; set; }
        private object lock_downloading = new object();
        public bool Closing { get; set; }
        /// <summary>
        /// 下载任务集合
        /// </summary>
        public List<DownloadTask> DownloadTaskList { get; set; }
        private object lock_DownloadTaskList = new object();
        /// <summary>
        /// 下载设备集合
        /// </summary>
        public List<dl_download_device> DownloadDeviceList { get; set; }

        public List<dl_server_config> DownloadServerList { get; set; }
        /// <summary>
        /// 当前下载进程集合
        /// </summary>
        public List<IDownloader> DownloaderList { get; set; }
        private object lock_DownloaderList = new object();
        /// <summary>
        /// 下载任务等待队列
        /// </summary>
        public List<dl_files> DownloadWaitingList { get; set; }
        private object lock_DownloadWaitingList = new object();
        /// <summary>
        /// 当前正在下载的文件
        /// </summary>
        public List<dl_files> DownloadingFiles { get; set; }
        public List<dl_files> DownloadFailList { get; set; }

        private fDisConnectCallBack m_DisConnectCallBack;
        private fHaveReConnectCallBack m_ReConnectCallBack;
        public NET_DEVICEINFO_Ex m_DeviceInfo;
        public IntPtr m_LoginID;

        private Thread downloadThread = null;
        private Thread heartbeatThread = null;
        private Thread refreshTaskThread = null;

        private string psdIP;
        private IPEndPoint tcpServerEP;
        private TcpManager tcpManager;

        public dl_download_device Device { get; set; }
        public string UUID { get; private set; }
        public List<DiskInfo> HardDiskList { get; set; }
        public List<CDRom> CDRomList { get; set; }


        /// <summary>
        /// 打开当前PSD客户端
        /// </summary>
        public void OpenPSDClient()
        {
            try
            {
                Init();

                var msg = new OpenClientMessage();
                msg.Device = this.Device;

                tcpManager.Send(tcpServerEP, msg);

                StartHeartBeat();
            }
            catch (Exception ex)
            { }
        }

        /// <summary>
        /// 关闭当前PSD客户端
        /// </summary>
        public void ClosePSDClient()
        {
            try
            {
                Closing = true;

                StopHeartBeat();

                if (DownloaderList.Count == 0)
                {
                    LogoutDownloadServer();
                }

                var msg = new CloseClientMessage();
                msg.DeviceId = this.UUID;
                tcpManager.Send(tcpServerEP, msg);

                StopTcpManager();
            }
            catch (Exception ex)
            { }
        }

        #region Init
        public void Init()
        {
            DownloadTaskList = new List<DownloadTask>();
            DownloaderList = new List<IDownloader>();
            DownloadDeviceList = new List<dl_download_device>();
            DownloadServerList = new List<dl_server_config>();
            DownloadWaitingList = new List<dl_files>();
            DownloadingFiles = new List<dl_files>();
            DownloadFailList = new List<dl_files>();

            m_DisConnectCallBack = new fDisConnectCallBack(DisConnectCallBack);
            m_ReConnectCallBack = new fHaveReConnectCallBack(ReConnectCallBack);

            try
            {
                //初始化大华NETCLIENT SDK
                DaHuaNetClient.Init(m_DisConnectCallBack, IntPtr.Zero, null);
                DaHuaNetClient.SetAutoReconnect(m_ReConnectCallBack, IntPtr.Zero);
            }
            catch (Exception ex)
            {

            }

            Running = true;
            Closing = false;
            Downloading = true;

            //加载当前PSD设备存储信息
            GetLocalStorage();

            //获取视频存储设备信息
            GetDownloadServerList();

            //注册当前设备
            UUID = DeviceUUID.GetUUID();
            this.Device = GetDeviceRegistInfo(UUID);

            if (this.Device != null)
            {
                Setting.MaxDownloadProcess = this.Device.max_download_process;

                //获取当前下载设备连接的大华存储设备信息
                var server = GetServerConfig(this.Device.dl_server_id);

                if (server != null)
                {
                    Setting.DownloadServerIP = server.storage_server_ip;
                    Setting.DownloadServerPort = (ushort)server.storage_server_port;
                    Setting.DownloadServerUserId = server.storage_server_user;
                    Setting.DownloadServerPwd = server.storage_server_password;
                }

                foreach (var hd in HardDiskList)
                {
                    hd.StorageType = GetStorageType(hd.DiskDriver);
                }
            }


            //获取并加载当前PSD设备的下载任务列表
            RefreshTaskInfo();


            //登录大华存储设备 
            LoginDownloadServer();
            //启动TCP服务
            StartTcpManager();

            StartDownload();
        }

        #region tcp manager
        /// <summary>
        /// 开始消息监听
        /// </summary>
        private void StartTcpManager()
        {
            tcpServerEP = new IPEndPoint(IPAddress.Parse(Setting.TcpServerAddress), Setting.TcpServerPort);
            psdIP = NetworkHelper.GetLocalIP();
            var ep = new IPEndPoint(IPAddress.Any, Setting.PSDPort);

            tcpManager = new TcpManager(ep);
            tcpManager.Received += TcpManager_Received;

            tcpManager.Start();

        }

        /// <summary>
        /// 停止消息监听
        /// </summary>
        private void StopTcpManager()
        {
            if (tcpManager != null)
            {
                tcpManager.Stop();
            }
        }

        /// <summary>
        /// 处理消息
        /// </summary>
        /// <param name="text"></param>
        /// <param name="remoteEp"></param>
        private void TcpManager_Received(string text, IPEndPoint remoteEp)
        {
            try
            {
                MessageBase msg = MessageParser.Parse(text);

                if (msg != null)
                {
                    var processor = ClientMessageProcessor.Parse(msg);

                    processor?.Run(this);
                }
            }
            catch (Exception ex)
            { }
        }
        #endregion

        #region init & regist psd device
        /// <summary>
        /// 查询指定设备的注册信息，若不存在则进行注册
        /// </summary>
        /// <param name="uuid"></param>
        /// <returns></returns>
        private dl_download_device GetDeviceRegistInfo(string uuid)
        {
            dl_download_device device = null;
            string response = HttpHelper.Get(Setting.API.GetDownloadDeviceInfo + "?deviceId=" + uuid);

            var result = JsonConvert.DeserializeObject<HResult<dl_download_device>>(response);

            if (result.success && result.data != null)
            {
                device = result.data;
                device.device_ip = NetworkHelper.GetLocalIP();
                device.device_port = Setting.PSDPort;
                var ms = HardDiskList.Where(t => t.DiskDriver == device.main_storage).FirstOrDefault();
                if (ms != null)
                {
                    device.main_storage_total = ms.SumSpace;
                    device.main_storage_free = ms.FreeSpace;
                }
                var ss = HardDiskList.Where(t => t.DiskDriver == device.second_storage).FirstOrDefault();
                if (ss != null)
                {
                    device.second_storage_total = ss.SumSpace;
                    device.second_storage_free = ss.FreeSpace;
                }
                return result.data;
            }
            else
            {
                device = new dl_download_device();
                device.id = uuid;
                device.device_ip = NetworkHelper.GetLocalIP();
                device.device_port = Setting.PSDPort;
                device.device_name = "下载设备_" + device.device_ip;
                device.device_connect_type = Setting.DeviceConnectType;
                device.data_path = Setting.DefaultDataPath;
                device.dl_server_id = (DownloadServerList.Count > 0 ? DownloadServerList[0].id : "");
                device.max_download_process = Setting.MaxDownloadProcess;
                device.state = 1;

                if (HardDiskList.Count > 0)
                {
                    var ms = HardDiskList[0];
                    device.main_storage = ms.DiskDriver;
                    device.main_storage_total = ms.SumSpace;
                    device.main_storage_free = ms.FreeSpace;

                    device.current_storage = device.main_storage;
                }

                if (HardDiskList.Count > 1)
                {
                    var ss = HardDiskList[1];
                    device.second_storage = ss.DiskDriver;
                    device.second_storage_total = ss.SumSpace;
                    device.second_storage_free = ss.FreeSpace;
                }

            }

            var res = RegistDevice(device);

            if (res.success)
            {
                return device;
            }
            else
            {
                MessageBox.Show("当前下载设备注册失败");
                return null;
            }
        }

        private bool CheckCurrentStorage()
        {
            bool result = false;

            //GetLocalStorage();
            UpdateLocalStorage();

            var disk = HardDiskList.Where(t => t.DiskDriver == this.Device.current_storage).FirstOrDefault();

            if (disk.FreeSpace / disk.SumSpace > 0.0005)
            {
                result = true;
            }
            else
            {
                double max_free = HardDiskList.Where(t => t.DiskDriver != this.Device.current_storage).Max(m => m.FreeSpace);

                var max_free_disk = HardDiskList.Where(t => t.DiskDriver != this.Device.current_storage && t.FreeSpace == max_free).FirstOrDefault();

                if (max_free_disk != null)
                {
                    this.Device.current_storage = max_free_disk.DiskDriver;

                    Dictionary<string, string> data = new Dictionary<string, string>();
                    data.Add("deviceId", this.UUID);
                    data.Add("currStorage", this.Device.current_storage);

                    var ret = HttpHelper.Post<HResult>(Setting.API.SetCurrentDownloadStorage, data);

                    result = ret.success;
                }
                else
                {
                    result = false;
                }
            }

            lock (lock_downloading)
            {
                Downloading = result;
            }

            return result;
        }

        /// <summary>
        /// 注册设备
        /// </summary>
        /// <param name="device"></param>
        /// <returns></returns>
        private HResult RegistDevice(dl_download_device device)
        {
            var result = HttpHelper.Post<HResult>(Setting.API.RegistDownloadDevice, JsonConvert.SerializeObject(device));

            return result;
        }

        /// <summary>
        /// 获取本机存储情况
        /// </summary>
        private void GetLocalStorage()
        {
            HardDiskList = new List<DiskInfo>();
            CDRomList = new List<CDRom>();

            string[] exclude_volumne = System.Configuration.ConfigurationManager.AppSettings["ExcludeVolumeName"].Split(",".ToCharArray());

            try
            {
                SelectQuery selectQuery = new SelectQuery("select * from win32_logicaldisk");

                ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery);

                ManagementObjectCollection diskcollection = searcher.Get();
                if (diskcollection != null && diskcollection.Count > 0)
                {
                    PSDClient.palDisk.Controls.Clear();

                    foreach (ManagementObject disk in diskcollection)
                    {
                        int nType = Convert.ToInt32(disk["DriveType"]);
                        if (nType == Convert.ToInt32(DriveType.Fixed))
                        {
                            if (!exclude_volumne.Contains(disk["VolumeName"].ToString()))
                            {
                                DiskInfo diskInfo = new DiskInfo();
                                diskInfo.DiskDriverChanged += DiskInfo_DiskDriverChanged;
                                diskInfo.MainStorageChanged += DiskInfo_MainStorageChanged;
                                diskInfo.SecondrayStorageChanged += DiskInfo_SecondrayStorageChanged;
                                diskInfo.SetNormalStorage += DiskInfo_SetNormalStorage;
                                PSDClient.palDisk.Controls.Add(diskInfo);
                                diskInfo.Dock = DockStyle.Left;
                                diskInfo.BringToFront();
                                diskInfo.DiskDriver = disk["DeviceID"].ToString();
                                diskInfo.VolumeName = disk["VolumeName"].ToString();
                                diskInfo.SumSpace = Convert.ToDouble(disk["Size"]);
                                diskInfo.FreeSpace = Convert.ToDouble(disk["FreeSpace"]);
                                diskInfo.StorageType = GetStorageType(diskInfo.DiskDriver);
                                HardDiskList.Add(diskInfo);
                            }
                        }
                        else if (nType == Convert.ToInt32(DriveType.CDRom))
                        {
                            //CDRom cd = new CDRom();
                            //PSDClient.palDisk.Controls.Add(cd);
                            //cd.Dock = DockStyle.Left;
                            //cd.BringToFront();
                            //cd.DiskDriver = disk["DeviceID"].ToString();
                            //cd.VolumeName = disk["Description"].ToString();
                            //CDRomList.Add(cd);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " GetLocalStorage " + ex.Message);
            }
        }

        private void UpdateLocalStorage()
        {
            try
            {
                SelectQuery selectQuery = new SelectQuery("select * from win32_logicaldisk");

                ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery);

                ManagementObjectCollection diskcollection = searcher.Get();

                foreach (ManagementObject disk in diskcollection)
                {
                    var d = HardDiskList.Where(t => t.DiskDriver == disk["DeviceID"].ToString()).FirstOrDefault();

                    if (d != null)
                    {
                        d.SumSpace = Convert.ToDouble(disk["Size"]);
                        d.FreeSpace = Convert.ToDouble(disk["FreeSpace"]);

                        if (this.Device.main_storage == disk["DeviceID"].ToString())
                        {
                            this.Device.main_storage_total = d.SumSpace;
                            this.Device.main_storage_free = d.FreeSpace;
                        }
                        else if (this.Device.second_storage == disk["DeviceID"].ToString())
                        {
                            this.Device.second_storage_total = d.SumSpace;
                            this.Device.second_storage_free = d.FreeSpace;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " UpdateLocalStorage " + ex.Message);
            }
        }

        private void DiskInfo_SetNormalStorage(object sender, EventArgs e)
        {
            this.SetNormalStorage((DiskInfo)sender);
        }

        private void DiskInfo_SecondrayStorageChanged(object sender, EventArgs e)
        {
            this.SetSecondaryStorage((DiskInfo)sender);
        }

        private void DiskInfo_MainStorageChanged(object sender, EventArgs e)
        {
            this.SetMainStorage((DiskInfo)sender);
        }

        private int GetStorageType(string partitionName)
        {
            if (this.Device != null)
            {
                if (partitionName == this.Device.main_storage)
                {
                    return 1;
                }
                else if (partitionName == this.Device.second_storage)
                {
                    return 2;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }

        /// <summary>
        /// 设置为主存储
        /// </summary>
        /// <param name="disk"></param>
        public void SetMainStorage(DiskInfo disk)
        {
            if (Downloading)
            {
                MessageBox.Show("请先停止所有下载任务后，再调整设置储存位置！");
                return;
            }

            HResult result = new HResult() { success = true };

            var old_main = HardDiskList.Where(t => t.StorageType == 1 && t.DiskDriver != disk.DiskDriver).FirstOrDefault();

            if (old_main != null)
            {
                old_main.StorageType = (int)DownloadStorageType.normal;
            }

            var old_second = HardDiskList.Where(t => t.StorageType == 2 && t.DiskDriver == disk.DiskDriver).FirstOrDefault();

            if (old_second != null)
            {
                Dictionary<string, string> data1 = new Dictionary<string, string>();
                data1.Add("deviceId", this.UUID);
                data1.Add("secondaryStorage", "");
                result = HttpHelper.Post<HResult>(Setting.API.SetSecondaryDownloadStorage, data1);
            }

            if (result.success)
            {
                Dictionary<string, string> data2 = new Dictionary<string, string>();
                data2.Add("deviceId", this.UUID);
                data2.Add("mainStorage", disk.DiskDriver);

                result = HttpHelper.Post<HResult>(Setting.API.SetMainDownloadStorage, data2);

                if (result.success)
                {
                    disk.StorageType = (int)DownloadStorageType.main;
                }
            }
        }

        /// <summary>
        /// 设置为副存储
        /// </summary>
        /// <param name="disk"></param>
        public void SetSecondaryStorage(DiskInfo disk)
        {
            if (Downloading)
            {
                MessageBox.Show("请先停止所有下载任务后，再调整设置储存位置！");
                return;
            }
            HResult result = new HResult() { success = true };

            var old_second = HardDiskList.Where(t => t.StorageType == 2 && t.DiskDriver != disk.DiskDriver).FirstOrDefault();

            if (old_second != null)
            {
                old_second.StorageType = (int)DownloadStorageType.normal;
            }

            var old_main = HardDiskList.Where(t => t.StorageType == 1 && t.DiskDriver == disk.DiskDriver).FirstOrDefault();

            if (old_second != null)
            {
                Dictionary<string, string> data1 = new Dictionary<string, string>();
                data1.Add("deviceId", this.UUID);
                data1.Add("mainStorage", "");
                result = HttpHelper.Post<HResult>(Setting.API.SetMainDownloadStorage, data1);
            }

            if (result.success)
            {
                Dictionary<string, string> data2 = new Dictionary<string, string>();
                data2.Add("deviceId", this.UUID);
                data2.Add("secondaryStorage", disk.DiskDriver);
                result = HttpHelper.Post<HResult>(Setting.API.SetSecondaryDownloadStorage, data2);

                if (result.success)
                {
                    disk.StorageType = (int)DownloadStorageType.secondary;
                }
            }
        }

        /// <summary>
        /// 设置为非下载存储
        /// </summary>
        /// <param name="disk"></param>
        public void SetNormalStorage(DiskInfo disk)
        {
            if (Downloading)
            {
                MessageBox.Show("请先停止所有下载任务后，再调整设置储存位置！");
                return;
            }
            HResult result = new HResult() { success = true };

            var old_main = HardDiskList.Where(t => t.StorageType == 1 && t.DiskDriver == disk.DiskDriver).FirstOrDefault();

            if (old_main != null)
            {
                Dictionary<string, string> data1 = new Dictionary<string, string>();
                data1.Add("deviceId", this.UUID);
                data1.Add("mainStorage", "");
                result = HttpHelper.Post<HResult>(Setting.API.SetMainDownloadStorage, data1);

                if (result.success)
                {
                    old_main.StorageType = (int)DownloadStorageType.normal;
                }
            }

            var old_second = HardDiskList.Where(t => t.StorageType == 2 && t.DiskDriver == disk.DiskDriver).FirstOrDefault();

            if (old_second != null)
            {
                Dictionary<string, string> data2 = new Dictionary<string, string>();
                data2.Add("deviceId", this.UUID);
                data2.Add("secondaryStorage", "");
                result = HttpHelper.Post<HResult>(Setting.API.SetSecondaryDownloadStorage, data2);

                if (result.success)
                {
                    old_second.StorageType = (int)DownloadStorageType.normal;
                }
            }
        }

        public void SetPSDName(string deviceName)
        {
            this.Device.device_name = deviceName;

            OnSetDeviceInfo?.Invoke(this.Device);
        }

        public void SetPSDMaxDownloadProcess(int process)
        {
            this.Device.max_download_process = process;
            Setting.MaxDownloadProcess = process;
        }

        private void DiskInfo_DiskDriverChanged(DiskInfo disk, string driverName)
        {
            if (Device != null)
            {
                if (Device.main_storage == driverName)
                {
                    disk.StorageType = 1;
                }
                else if (Device.second_storage == driverName)
                {
                    disk.StorageType = 2;
                }
                else
                {
                    disk.StorageType = 0;
                }
            }
            else
            {
                disk.StorageType = 0;
            }
        }
        #endregion

        #region HeartBeat

        /// <summary>
        /// 启动心跳线程
        /// </summary>
        private void StartHeartBeat()
        {
            Running = true;
            heartbeatThread = new Thread(new ThreadStart(SendHeartBeat));
            heartbeatThread.Start();
        }

        /// <summary>
        /// 执行发送心跳，更新设备状态到服务端
        /// </summary>
        private void SendHeartBeat()
        {
            while (Running)
            {
                UpdateLocalStorage();

                var msg = new PSDHeartBeatMessage() { Heartbeart = new PSDHeartbeat() };
                msg.Heartbeart.DeviceId = this.Device.id;
                msg.Heartbeart.DeviceIP = this.Device.device_ip;
                msg.Heartbeart.DeviceInfo = this.Device;
                //msg.Heartbeart.DownloadState = (Downloading ? 1 : 0);
                //msg.Heartbeart.BurnState = 0;
                //msg.Heartbeart.MainStorage = this.Device.main_storage;
                //msg.Heartbeart.MainStorageTotal = this.Device.main_storage_total;
                //msg.Heartbeart.MainStorageFree = this.Device.main_storage_free;
                //msg.Heartbeart.SecondaryStorage = this.Device.second_storage;
                //msg.Heartbeart.SecondaryStorageTotal = this.Device.second_storage_total;
                //msg.Heartbeart.SecondaryStorageFree = this.Device.second_storage_free;

                tcpManager.Send(tcpServerEP, msg);

                Thread.Sleep(20 * 1000);
            }
        }

        /// <summary>
        /// 停止发送心跳
        /// </summary>
        private void StopHeartBeat()
        {
            try
            {
                Running = false;
                heartbeatThread.Abort();
            }
            catch
            { }

        }
        #endregion

        #region refresh task
        /// <summary>
        /// 开始刷新当前设备任务
        /// </summary>
        private void StartRefreshTaskInfo()
        {
            refreshTaskThread = new Thread(new ThreadStart(delegate ()
            {
                while (Running)
                {
                    RefreshTaskInfo();

                    Thread.Sleep(1000 * 60);
                }
            }));

            refreshTaskThread.Start();
        }

        /// <summary>
        /// 刷新当前设备的下载任务信息
        /// </summary>
        /// <returns></returns>
        public void RefreshTaskInfo()
        {
            lock (lock_DownloadTaskList)
            {
                var result_task = HttpHelper.Get<HResult<List<dl_task>>>(Setting.API.GetDownloadingTaskList + "?deviceId=" + this.UUID);

                if (result_task.success)
                {
                    foreach (var task in result_task.data)
                    {
                        var result_channel = HttpHelper.Get<HResult<List<dl_task_channel>>>(Setting.API.GetChannelList + "?taskId=" + task.id);
                        List<dl_task_channel> channels = null;

                        if (result_channel.success)
                        {
                            channels = result_channel.data;
                        }


                        var dt = DownloadTaskList.Where(t => t.Task.id == task.id).FirstOrDefault();
                        if (dt == null)
                        {
                            dt = new DownloadTask();
                            dt.Task = task;
                            dt.ChannelList = channels;
                            DownloadTaskList.Add(dt);
                        }
                        else
                        {
                            dt.Task = task;
                            dt.ChannelList = channels;
                        }

                        OnCreateTask?.Invoke(task, channels);
                    }
                }
            }
        }

        #endregion

        #endregion

        #region set download state
        public HResult StartDownloadTask(string taskId)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("taskId", taskId);
            var result = HttpHelper.Post<HResult>(Setting.API.StartDownloadTask, data);

            if (result.success)
            {
                OnDownloadTaskStateChanged?.Invoke(taskId, 1);
            }

            return result;
        }

        public HResult StopDownloadTask(string taskId)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("taskId", taskId);
            var result = HttpHelper.Post<HResult>(Setting.API.StopDownloadTask, data);

            if (result.success)
            {
                OnDownloadTaskStateChanged?.Invoke(taskId, 0);
            }

            return result;
        }

        public HResult FinishDownloadTask(string taskId)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("taskId", taskId);
            var result = HttpHelper.Post<HResult>(Setting.API.FinishDownloadTask, data);

            if (result.success)
            {
                OnDownloadTaskStateChanged?.Invoke(taskId, 2);

            }
            return result;
        }

        public HResult RestartDownloadTask(string taskId)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("taskId", taskId);
            var result = HttpHelper.Post<HResult>(Setting.API.RestartDownloadTask, data);

            //if (result.success)
            //{
            //    OnDownloadTaskStateChanged?.Invoke(taskId, 1);
            //}
            return result;
        }

        public HResult StartDownloadChannel(string channelId)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("channelId", channelId);
            var result = HttpHelper.Post<HResult>(Setting.API.StartDownloadChannel, data);

            if (result.success)
            {
                OnDownloadChannelStateChanged?.Invoke(channelId, 1);
            }

            return result;
        }

        public HResult StopDownloadChannel(string channelId)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("channelId", channelId);
            var result = HttpHelper.Post<HResult>(Setting.API.StopDownloadChannel, data);

            if (result.success)
            {
                OnDownloadChannelStateChanged?.Invoke(channelId, 0);
            }

            return result;
        }

        public HResult FinishDownloadChannel(string channelId)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("channelId", channelId);
            var result = HttpHelper.Post<HResult>(Setting.API.FinishDownloadChannel, data);

            if (result.success)
            {
                OnDownloadChannelStateChanged?.Invoke(channelId, 2);
            }

            return result;
        }

        public HResult RestartDownloadChannel(string channelId)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("channelId", channelId);
            var result = HttpHelper.Post<HResult>(Setting.API.RestartDownloadChannel, data);

            //if (result.success)
            //{
            //    OnDownloadChannelStateChanged?.Invoke(channelId, 1);
            //}

            return result;
        }

        #endregion

        #region DaHua Download
        /// <summary>
        /// 初始化下载助手，登录大华存储设备、启动tcp消息服务
        /// </summary>
        /// <returns></returns>
        public IntPtr LoginDownloadServer()
        {
            //登录大华存储设备
            m_DeviceInfo = new NET_DEVICEINFO_Ex();

            m_LoginID = DaHuaNetClient.LoginWithHighLevelSecurity(Setting.DownloadServerIP,
                Setting.DownloadServerPort,
                Setting.DownloadServerUserId,
                Setting.DownloadServerPwd,
                EM_LOGIN_SPAC_CAP_TYPE.TCP,
                IntPtr.Zero,
                ref m_DeviceInfo);

            if (IntPtr.Zero == m_LoginID)
            {
                MessageBox.Show("登录存储设备失败");// FileInfo.error_log = NETClient.GetLastError();
            }

            return m_LoginID;
        }

        /// <summary>
        /// 登出下载服务器，停止tcp消息监听
        /// </summary>
        public void LogoutDownloadServer()
        {
            try
            {
                bool result = DaHuaNetClient.Logout(m_LoginID);
                //if (!result)
                //{
                //    MessageBox.Show(NETClient.GetLastError());
                //}
                m_LoginID = IntPtr.Zero;
            }
            catch { }
        }

        private void DisConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser)
        {
            //
        }

        private void ReConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser)
        {
            //
        }

        /// <summary>
        /// 获取大华存储设备信息
        /// </summary>
        public void GetDownloadServerList()
        {
            var result = HttpHelper.Get<HResult<List<dl_server_config>>>(Setting.API.GetDownloadServerConfig);

            if (result.success)
            {
                DownloadServerList = result.data;
            }
        }

        /// <summary>
        /// 得到一个下载服务器配置
        /// </summary>
        /// <param name="serverId"></param>
        /// <returns></returns>
        public dl_server_config GetServerConfig(string serverId)
        {
            return DownloadServerList.Where(t => t.id == serverId).FirstOrDefault();
        }

        /// <summary>
        /// 开始下载
        /// </summary>
        public void StartDownload()
        {
            ResetDownloadingFiles();

            GetDownloadWaitingFiles();

            OnStartDownload?.Invoke();

            //DoWork();

            StartRefreshTaskInfo();
        }

        /// <summary>
        /// 停止下载
        /// </summary>
        public void StopDownload()
        {
            if (DownloaderList.Count > 0)
            {
                Closing = true;
            }
            else
            {
                Running = false;
            }

            OnStopDownload?.Invoke();
        }

        private void ResetDownloadingFiles()
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("deviceId", this.Device.id);
            var result = HttpHelper.Post<HResult>(Setting.API.ResetDownloadingFiles, data);
        }

        /// <summary>
        /// 处理未完成的文件下载任务
        /// </summary>
        public void GetDownloadWaitingFiles()
        {
            //string taskIdArray = "";

            //lock (lock_DownloadTaskList)
            //{
            //    //查询本设备所有未完成下载的文件
            //    taskIdArray = string.Join(",", DownloadTaskList.Select(t => t.Task.id).ToArray());
            //}

            var result_file = HttpHelper.Get<HResult<List<dl_files>>>(Setting.API.GetDownloadWaitingFiles + "?deviceId=" + this.Device.id);

            if (result_file.success && result_file.data != null)
            {
                lock (lock_DownloadWaitingList)
                {
                    DownloadWaitingList.Clear();

                    foreach (var file in result_file.data)
                    {
                        //if (DownloaderList.Count < Setting.MaxDownloadProcess)
                        //{
                        //    //下载队列数量未达到上限时，创建新的下载
                        //    CreateDownload(file);
                        //}
                        //else
                        //{
                        //否则，添加到下载等待队列
                        DownloadWaitingList.Add(file);
                        //}
                    }
                }
            }
        }

        /// <summary>
        /// 执行文件下载过程,
        /// 
        /// 循环下载任务的方法，必须放在主线程中通过窗体上的Timer控件来调用，否则会和大华下载SDK的内部线程管理代码冲突，导致SDK内部线程被挂起，无法退出
        /// </summary>
        public void DoWork()
        {
            if (Downloading && !Closing)
            {
                if (DownloaderList.Count < Setting.MaxDownloadProcess)
                {
                    //如果存在上次未完成的下载，则先执行下载等待队列的内容
                    dl_files waitingFile = null;
                    lock (lock_DownloadWaitingList)
                    {
                        if (DownloadWaitingList.Count > 0)
                        {
                            waitingFile = DownloadWaitingList[0];
                        }
                    }

                    if (waitingFile != null)
                    {
                        CreateDownload(waitingFile);
                    }
                    else
                    {
                        lock (lock_DownloadTaskList)
                        {
                            //依次循环当前设备的所有任务，创建最近一个需要下载的文件
                            foreach (var task in DownloadTaskList)
                            {
                                if (task.Task.download_state != (int)DownloadTaskSate.开始下载)
                                {
                                    return;
                                }

                                bool ignoreTime = false;

                                //得到当前任务的下载通道，存在多个下载通道的时候，根据通道顺序，依次循环开始下载
                                var channel = task.GetCurrentChannel();

                                if (channel != null && channel.download_state == (int)DownloadChanelState.正在下载)
                                {
                                    if (CheckCurrentStorage())
                                    {
                                        //创建该下载通道的下一个文件
                                        var ret = CreateNextDownload(channel.id, ignoreTime);

                                        if (ret.success)
                                        {
                                            //创建成功后，将下载序列转移到该任务的下一个通道
                                            task.MoveToNextChannel();
                                        }
                                    }
                                }
                                else
                                {
                                    task.MoveToNextChannel();
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 根据下载内容创建一个下载进程
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public HResult CreateDownload(dl_files file)
        {
            HResult result = null;

            lock (lock_DownloadWaitingList)
            {
                var f = DownloadWaitingList.Where(t => t.id == file.id).FirstOrDefault();
                if (f != null)
                {
                    DownloadWaitingList.Remove(f);
                }
            }

            if (file.state == 2)
            {
                Dictionary<string, string> data = new Dictionary<string, string>();
                data.Add("fileId", file.id);
                data.Add("state", "0");
                var ret = HttpHelper.Post<HResult>(Setting.API.SetFileState, data);
            }

            var task = DownloadTaskList.Where(t => t.Task.id == file.dl_task_id).FirstOrDefault();

            //创建大华存储设备下载器
            var downloader = new DH_EVS_Downloader();
            downloader.m_LoginID = this.m_LoginID;
            downloader.m_DeviceInfo = this.m_DeviceInfo;
            downloader.Id = file.id;
            downloader.ServerIP = Setting.DownloadServerIP;
            downloader.ServerPort = (ushort)Setting.DownloadServerPort;
            downloader.UserId = Setting.DownloadServerUserId;
            downloader.Password = Setting.DownloadServerPwd;

            downloader.UpdateDownloadProgress += Downloader_UpdateDownloadProgress;
            downloader.FileDownloadSuccess += Downloader_FileDownloadSuccess;
            downloader.FileDownloadFail += Downloader_FileDownloadFail;

            lock (lock_DownloaderList)
            {
                this.DownloaderList.Add(downloader);
            }

            result = downloader.Download(file);

            if (result.success)
            {
                DownloadFailList.Remove(file);
                DownloadingFiles.Add(file);

                var ret = HttpHelper.Post<HResult>(Setting.API.StartDownloadFile,
                    new Dictionary<string, string> {
                        { "fileId", file.id}
                    });

                //触发创建事件，在FrmMain上更新UI，并创建下载组件
                OnCreateDownload?.Invoke(file);
            }

            return result;
        }


        /// <summary>
        /// 更新下载进度事件
        /// </summary>
        /// <param name="file"></param>
        public void Downloader_UpdateDownloadProgress(dl_files file, int time)
        {
            OnUpdateDownloadProgress?.Invoke(file, time);
        }

        /// <summary>
        ///下载成功事件
        /// </summary>
        /// <param name="file"></param>
        public void Downloader_FileDownloadSuccess(dl_files file)
        {
            try
            {
                RemoveDownloader(file);
                DownloadingFiles.Remove(file);

                var response = HttpHelper.Post(Setting.API.DownloadSuccess, JsonConvert.SerializeObject(file));

                OnFileDownloadSuccess?.Invoke(file);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " Downloader_FileDownloadSuccess " + ex.Message);
            }
            finally
            {
                if (Closing)
                {
                    //if (DownloaderList.Count == 0)
                    //{
                    //    OnClosing?.Invoke();
                    //}

                    Running = false;
                    Downloading = false;
                }
            }
        }

        /// <summary>
        /// 下载失败事件
        /// </summary>
        /// <param name="file"></param>
        public void Downloader_FileDownloadFail(dl_files file)
        {
            try
            {
                RemoveDownloader(file);
                DownloadingFiles.Remove(file);
                DownloadFailList.Add(file);

                var response = HttpHelper.Post(Setting.API.DownloadFail, JsonConvert.SerializeObject(file));

                OnFileDownloadFail?.Invoke(file);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " Downloader_FileDownloadFail " + ex.Message);
            }
            finally
            {
                if (Closing)
                {
                    Running = false;
                    Downloading = false;
                }
            }
        }

        /// <summary>
        /// 移除下载器
        /// </summary>
        /// <param name="file"></param>
        private void RemoveDownloader(dl_files file)
        {
            lock (lock_DownloaderList)
            {
                var downloader = DownloaderList.Where(t => t.Id == file.id).FirstOrDefault();

                if (downloader != null)
                {
                    DownloaderList.Remove(downloader);
                }
            }
        }

        /// <summary>
        /// 创建指定通道的下一个下载进程
        /// </summary>
        /// <param name="channelId"></param>
        /// <param name="ignoreTime"></param>
        /// <returns></returns>
        public HResult<dl_files> CreateNextDownload(string channelId, bool ignoreTime)
        {
            //在服务端创建下一个要下载的文件信息，记录到数据库，并返回文件信息
            string url = Setting.API.GetNextDownloadFile + "?channelId=" + channelId + "&ignoreTime=" + (ignoreTime ? 1 : 0);
            var result = HttpHelper.Get<HResult<dl_files>>(url);

            if (result.success)
            {
                //根据创建的文件信息开始下载
                var ret = CreateDownload(result.data);

                result.success = ret.success;
                result.message = ret.message;
            }

            return result;
        }

        #endregion

        ///// <summary>
        ///// 向管理端发送PSD设备运行情况，包括设备基本信息、存储信息、CDROM信息、当前下载内容、下载错异常信息
        ///// </summary>
        ///// <param name="managerEP"></param>
        //public void ResponsePSDDetail(IPEndPoint managerEP)
        //{
        //    var detail = new PSDDetail();
        //    detail.Device = Device;

        //    foreach (var disk in HardDiskList)
        //    {
        //        var storage = new StorageInfo();
        //        storage.DiskDriver = disk.DiskDriver;
        //        storage.VolumeName = disk.VolumeName;
        //        storage.SumSpace = disk.SumSpace;
        //        storage.FreeSpace = disk.FreeSpace;
        //        storage.StorageType = disk.StorageType;

        //        detail.StorageList.Add(storage);
        //    }

        //    foreach (var cd in CDRomList)
        //    {
        //        var cdrom = new CDRomInfo();
        //        cdrom.CDRomDriver = cd.DiskDriver;
        //        cdrom.VolumeName = cd.VolumeName;

        //        detail.CDRomList.Add(cdrom);
        //    }

        //    for (int i = DownloadingFiles.Count - 1; i >= 0; i--)
        //    {
        //        detail.DownloadingFiles.Insert(0, DownloadingFiles[i]);
        //    }

        //    for (int i = DownloadFailList.Count - 1; i >= 0; i--)
        //    {
        //        detail.FailList.Insert(0, DownloadFailList[i]);
        //    }

        //    var msg = new ResponsePSDDownloadingFilesMessage();
        //    msg.PSDDetail = detail;

        //    tcpManager.Send(managerEP, msg);
        //}
    }
}
